typedef struct Event {
    int event_type;                             //事件类型
    int event_code;                             //事件类型下的事件代码
    int event_data;
    char event_data_extra[MAX_EVENT_DATA_LEN];  //与事件相关联的数据
} Event;

struct State;
typedef struct Transition {
    int event_type;         //迁移事件
    int event_code;
    int event_data;
    int action_code;        //要执行的动作编号，action == 动作编号
    int action_extra_data;  //extra data for action
    int state_code;         //新状态编号
    State *state;            //redundant for efficiency, which is a pointer to state_code object
    Transition *next;       //下一个Transition，以构建链表

    Transition(int et, int ec, int ed, int ac, int aed, int sc):
        event_type(et), event_code(ec), event_data(ed),
        action_code(ac), action_extra_data(aed),
        state_code(sc),
        state(nullptr), next(nullptr) {
    }
} Transition;

typedef struct State {
    int state_code;                //状态编号；
    int entry_action;             //入口动作编号
    int entry_action_extra_data;  //extra data for entry action
    int exit_action;              //出口动作编号
    int exit_action_extra_data;   //extra data for exit action
    int new_state_code;           //enter a new state directly
    Transition *transition;       //状态迁移表
    State *next;

    State(int sc, int ena, int enaed, int exa, int exaed, int nsc = -1):
        state_code(sc),
        entry_action(ena), entry_action_extra_data(enaed),
        exit_action(exa), exit_action_extra_data(exaed),
        new_state_code(nsc),
        transition(nullptr), next(nullptr){
    }
} State;

typedef int (*Action) (Event *, int event_len, int extra_data);
typedef struct ActionTable {
    int action_code;
    Action action;
} ActionTable;

class FSM {
public:
    explicit FSM(std::string n);
    ~FSM();
    FSM& operator+(State *state);
    FSM& operator+(Transition *trans);
    FSM& done();
    bool set_current(int state_code);
    void set_actions(ActionTable *at, int n);
    int run(Event& event, int event_len);

private:
    std::string name;
    Logger *logger;
    State *machine;
    State *current;
    ActionTable *actions;
    int noa;                  //number of actions
};
